package network

import (
	"fmt"
	"net"
	"time"
)

// params addr "127.0.0.1:888"
func StartTcpServer(addr string, maxConn int32) (*TCPServer, error) {
	tcpaddr, err := net.ResolveTCPAddr("tcp", addr)
	if err != nil {
		return nil, err
	}

	listen, err := net.ListenTCP("tcp", tcpaddr)
	if err != nil {
		return nil, err
	}

	if maxConn == 0 {
		maxConn = 1
	}

	s := &TCPServer{
		addr:     addr,
		listener: listen,
		maxConn:  maxConn,
		//readChan: make(chan *RecvPacketType, ID_READ_CHAN_LENGTH),
	}

	s.run()
	fmt.Println("StartTcpServer addr ", addr)
	return s, nil
}

func (m *TCPServer) run() {
	go m.accept()
}

func (m *TCPServer) accept() {
	defer m.listener.Close()
	for {
		tcpConn, err := m.listener.AcceptTCP()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				time.Sleep(100 * time.Millisecond)
				continue
			}

			fmt.Printf("tcp_server addr %v Accept Error: %v\n", m.addr, err)
			return
		}

		curCount := m.ConnectionCount()
		if curCount >= m.maxConn {
			fmt.Printf("tcp_server addr %v Accept connection full curCount %v, max: %v \n", m.addr, curCount, m.maxConn)
			tcpConn.Close()
			continue
		}

		client := newTCPClient(tcpConn, m)

		fmt.Printf("tcp_server addr %v new Accept curconn %v\n", client.RemoteAddr(), m.ConnectionCount())
	}
}

func (m *TCPServer) FindConnect(guid int64) (*TCPClient, bool) {
	if v, ok := m.connectMap.Load(guid); ok {
		return v.(*TCPClient), true
	}
	return nil, false
}

func (m *TCPServer) BroadcastData(data *SendPacket) {
	m.connectMap.Range(func(k, v interface{}) bool {
		client := v.(*TCPClient)
		p := GetSendPack(len(data.Data))
		copy(p.Data, data.Data)
		client.SendData(data)
		return true
	})
	DeallocateSendPacket(data)
}

func (m *TCPServer) SendData(guid int64, data *SendPacket) bool {
	if v, ok := m.connectMap.Load(guid); ok {
		client := v.(*TCPClient)
		client.SendData(data)
		return true
	}
	return false
}

func (m *TCPServer) CloseConnect(guid int64) {
	if v, ok := m.connectMap.Load(guid); ok {
		client := v.(*TCPClient)
		client.Close()
	}
}

func (m *TCPServer) ConnectionCount() int32 {
	return m.curConnNum
}
